package com.masonluo.mlonlinejudge.controller;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.masonluo.mlonlinejudge.model.vo.StatsOfTableVo;
import com.masonluo.mlonlinejudge.model.vo.StatsOfWeekVo;
import com.masonluo.mlonlinejudge.model.vo.StatsOfWeeksVo;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.utils.URIBuilder;
import org.springframework.http.*;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.net.URISyntaxException;
import java.time.*;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * @Author: shenma
 * @Date: 2024/3/27  6:20
 * 提供umami数据给datagear看板
 */
@RestController
@Slf4j
@RequestMapping("/umami")
public class UmamiController {

    private final RestTemplate restTemplate;
    private final String ip = "http://106.53.210.134:3000"; // 主机ip
    private final String activeUrl = ip + "/api/websites/7504e955-ec39-4696-8786-8fdd216ef7dd/active";
    private final String statsUrl = ip + "/api/websites/7504e955-ec39-4696-8786-8fdd216ef7dd/stats";
    private final String tokenUrl = ip + "/api/auth/login";
    private final String pwd = "umami"; // umami密码
    @Getter
    private String umamiToken;

    public UmamiController(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }

    public static String extractToken(String responseBody) throws IOException {
        ObjectMapper objectMapper = new ObjectMapper();
        JsonNode jsonNode = objectMapper.readTree(responseBody);

        // 提取token
        JsonNode tokenNode = jsonNode.get("token");
        if (tokenNode != null) {
            return tokenNode.asText();
        } else {
            throw new IllegalArgumentException("Token not found in the response body");
        }
    }

    @Scheduled(fixedRate = 86400000) // 3600000毫秒 = 1小时 ==> 1天
    public void fetchToken() {
        try {
            // 设置请求头为application/json类型
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);

            // 创建请求体（根据实际情况替换为实际的JSON对象）
            String requestBody = "{\"username\": \"admin\",\"password\": \"" + pwd + "\"}";

            // 创建请求实体对象
            HttpEntity<String> requestEntity = new HttpEntity<>(requestBody, headers);

            // 发送POST请求获取token
            ResponseEntity<String> response = restTemplate.postForEntity(tokenUrl, requestEntity, String.class);

            // 提取token
            umamiToken = extractToken(response.getBody());
            System.out.println("Fetched token: " + getUmamiToken());
        } catch (Exception e) {
            System.err.println("Error fetching token: " + e.getMessage());
        }
    }


    /**
     * 当前活跃人数
     * @return
     */
    @GetMapping("/active")
    public ResponseEntity<?> getActiveCount() {
        // 设置请求头
        HttpEntity<MultiValueMap<String, Object>> httpEntity = setHeaders();
        // 发送GET请求
        // ResponseEntity<String> response = restTemplate.getForEntity(activeUrl, String.class, headers);
        ResponseEntity<String> response = restTemplate.exchange(activeUrl, HttpMethod.GET, httpEntity,String.class);

        // 返回响应
        return ResponseEntity.ok(Objects.requireNonNull(response.getBody()));
    }

    /**
     * 站点统计信息  今日
     * @return
     */
    @GetMapping("/stats/today")
    public ResponseEntity<?> getTodayStats() {
        String statsUrlWithParameters = buildTodayUrl(statsUrl);
        // System.out.println("完整路径：" + statsUrlWithParameters);

        // 发送GET请求
        ResponseEntity<String> response = responseOfGet(statsUrlWithParameters);

        // 返回响应
        return ResponseEntity.ok(Objects.requireNonNull(response.getBody()));
    }

    /**
     * 站点统计信息  昨日
     * @return
     */
    @GetMapping("/stats/yesterday")
    public ResponseEntity<?> getYesterdayStats() {
        String statsUrlWithParameters = buildYesterdayUrl(statsUrl);
        // 发送GET请求并返回响应体
        ResponseEntity<String> response = responseOfGet(statsUrlWithParameters);
        // 返回响应
        return ResponseEntity.ok(Objects.requireNonNull(response.getBody()));
    }

    /**
     * 站点统计信息  近一周中每天访客量
     * @return
     */
    @GetMapping("/stats/week")
    public ResponseEntity<?> getStatsOfWeekTendency() {
        StatsOfWeeksVo statsOfWeeksVo = buildStatsOfWeeksVo();
        // 返回响应
        return ResponseEntity.ok(Objects.requireNonNull(statsOfWeeksVo));
    }

    /**
     * 站点统计信息  列表==> 昨日、今日、本周、本月、本季度、本年
     * @return
     */
    @GetMapping("/stats/table")
    public ResponseEntity<?> getStatsOfTable() {
        StatsOfTableVo statsOfTableVo = buildStatsOfTableVo();
        // 返回响应
        return ResponseEntity.ok(Objects.requireNonNull(statsOfTableVo));
    }

    public StatsOfWeeksVo buildStatsOfWeeksVo() {
        StatsOfWeeksVo statsOfWeeksVo = new StatsOfWeeksVo();
        List<StatsOfWeekVo> list = new ArrayList<>(7);

        ObjectMapper objectMapper = new ObjectMapper();

        LocalDate today = LocalDate.now();
        for (int i = 6; i >= 0; i--) {
            // 遍历近一周
            LocalDate date = today.minusDays(i);
            StatsOfWeekVo statsOfWeekVo = new StatsOfWeekVo();
            statsOfWeekVo.setCount(Integer.parseInt(getUniquesValue(objectMapper,responseOfGet(buildUrlOfDay(date,statsUrl)))));
            statsOfWeekVo.setDate(date.toString());
            list.add(statsOfWeekVo);

        }
        statsOfWeeksVo.setList(list);
        return statsOfWeeksVo;
    }


    public StatsOfTableVo buildStatsOfTableVo() {
        StatsOfTableVo statsOfTableVo = new StatsOfTableVo();
        ObjectMapper objectMapper = new ObjectMapper();

        String todayUrl = buildTodayUrl(statsUrl);
        String yesterdayUrl = buildYesterdayUrl(statsUrl);
        String weekUrl = buildWeekUrl(statsUrl);
        String monthUrl = buildMonthUrl(statsUrl);
        String yearUrl = buildYearUrl(statsUrl);

        statsOfTableVo.setCountOfToday(Integer.parseInt(getUniquesValue(objectMapper,responseOfGet(todayUrl))));
        statsOfTableVo.setCountOfYesterday(Integer.parseInt(getUniquesValue(objectMapper,responseOfGet(yesterdayUrl))));
        statsOfTableVo.setCountOfWeek(Integer.parseInt(getUniquesValue(objectMapper,responseOfGet(weekUrl))));
        statsOfTableVo.setCountOfMonth(Integer.parseInt(getUniquesValue(objectMapper,responseOfGet(monthUrl))));
        statsOfTableVo.setCountOfYear(Integer.parseInt(getUniquesValue(objectMapper,responseOfGet(yearUrl))));

        // System.out.println("构建好的statsOfTableVo: " + statsOfTableVo);

        return statsOfTableVo;
    }

    public String getUniquesValue(ObjectMapper objectMapper, ResponseEntity<String> responseEntity) {
        JsonNode rootNode = null;
        String body = responseEntity.getBody();

        try {
            rootNode = objectMapper.readTree(body);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
        JsonNode uniquesNode = rootNode.path("uniques");
        return uniquesNode.get("value").toString();
    }

    public ResponseEntity<String> responseOfGet(String url) {
        // 设置请求头
        HttpEntity<MultiValueMap<String, Object>> httpEntity = setHeaders();
        // 发送GET请求
        return restTemplate.exchange(url, HttpMethod.GET, httpEntity,String.class);
    }

    public String buildTodayUrl(String url) {
        // 获取今日日期
        LocalDate today = LocalDate.now();
        return buildUrlOfDay(today, url);
    }

    public String buildYesterdayUrl(String url) {
        // 获取昨日日期
        LocalDate yesterday = LocalDate.now().minusDays(1);
        return buildUrlOfDay(yesterday, url);
    }

    // TODO 未写完
    public String buildWeekUrl(String url) {
        LocalDate today = LocalDate.now();
        return buildUrlOfWeek(today, url);
    }

    private String buildUrlOfWeek(LocalDate today, String url) {
        // 本周一
        LocalDate firstDayOfWeek  = today.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
        // 本周日
        LocalDate lastDayOfWeek  = today.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));
        LocalDateTime start = firstDayOfWeek.atStartOfDay();
        LocalDateTime end = lastDayOfWeek.atTime(LocalTime.MAX);
        return buildUrlWithParameters(url, getTimestamp(start), getTimestamp(end));
    }

    public String buildMonthUrl(String url) {
        LocalDate today = LocalDate.now();
        return buildUrlOfMonth(today, url);
    }

    private String buildUrlOfMonth(LocalDate today, String url) {
        // 月份第一天
        LocalDate firstDayOfMonth  = today.with(TemporalAdjusters.firstDayOfMonth());
        LocalDate lastDayOfMonth  = today.with(TemporalAdjusters.lastDayOfMonth());
        LocalDateTime start = firstDayOfMonth.atStartOfDay();
        LocalDateTime end = lastDayOfMonth.atTime(LocalTime.MAX);

        return buildUrlWithParameters(url, getTimestamp(start),getTimestamp(end));
    }

    public String buildYearUrl(String url) {
        LocalDate today = LocalDate.now();
        return buildUrlOfYear(today, url);
    }

    private String buildUrlOfYear(LocalDate today, String url) {
        LocalDate firstDayOfYear  = today.with(TemporalAdjusters.firstDayOfYear());
        LocalDate lastDayOfYear  = today.with(TemporalAdjusters.lastDayOfYear());
        LocalDateTime start = firstDayOfYear.atStartOfDay();
        LocalDateTime end = lastDayOfYear.atTime(LocalTime.MAX);

        return buildUrlWithParameters(url, getTimestamp(start), getTimestamp(end));
    }
    //


    public String buildUrlOfDay(LocalDate day, String url) {
        LocalDateTime startOfYesterday = day.atStartOfDay();
        LocalDateTime endOfYesterday = day.atTime(LocalTime.MAX);
        // 获取时间戳（毫秒）
        long startTimeOfDayMillis = getTimestamp(startOfYesterday);
        // 获取时间戳（毫秒）
        long endTimeOfDayMillis = getTimestamp(endOfYesterday);
        return buildUrlWithParameters(url,startTimeOfDayMillis,endTimeOfDayMillis);
    }

    public long getTimestamp(LocalDateTime localDateTime) {
        return localDateTime.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
    }

    public String buildUrlWithParameters(String baseUrl, Long startTimeOfDayMillis, Long endTimeOfDayMillis) {
        // 构造uri
        URIBuilder uriBuilder = null;
        try {
            uriBuilder = new URIBuilder(baseUrl);
        } catch (URISyntaxException e) {
            throw new RuntimeException(e);
        }
        uriBuilder.addParameter("startAt", String.valueOf(startTimeOfDayMillis));
        uriBuilder.addParameter("endAt", String.valueOf(endTimeOfDayMillis));

        try {
            return uriBuilder.build().toString();
        } catch (URISyntaxException e) {
            throw new RuntimeException(e);
        }
    }

    public HttpEntity<MultiValueMap<String, Object>> setHeaders() {
        // 设置请求头
        HttpHeaders headers = new HttpHeaders();
        headers.set("Accept", "application/json");
        headers.set("Authorization", "Bearer " + getUmamiToken());
        return new HttpEntity<>(headers);
    }

}
